#pragma once


#include <memory>
#include <poll.h>
#include "Sock.hpp"

const int defaultfd = -1;

class Pollserver
{
    static const int fds_array_num = 1024;         // 设置默认要进行等待的数组长度
public:
    Pollserver(uint port)
        :_sock_ptr(new Sock(port))
    {
        for(int i = 0 ; i < fds_array_num ; i++)
        {
            _fds_array[i].fd = defaultfd;             
        }
    }

    void AddToArray(int fd , short events)
    {
        // 1. 找空位置
        // 2. 加入fd

        int pos = 0;
        for(; pos < fds_array_num && _fds_array[pos].fd != -1 ; pos++) 
        ;

        if(pos == fds_array_num)
        {
            // 数组不够了
            // 1. 打印日志信息
            // 2. 关闭文件描述符

            Log(Warning) << "array is full";
            close(fd);
        }
        else
        {
            // 加入fd
            _fds_array[pos].fd = fd;
            _fds_array[pos].events = events;
            Log(Info) << "get a connect  , fd : " << fd; 
        }
    }

    void Init()
    {
        // 1. 创建套接字
        // 2. 进行绑定
        // 3. 设置监听模式
        // 4. 将网络套接字加到_fds_array数组中

        _sock_ptr->Socket();
        _sock_ptr->Bind();
        _sock_ptr->Listen();

        AddToArray(_sock_ptr->Get_fd() , POLLIN);
    }

    void Sockfd_Ready()
    {
        int listensock = _sock_ptr->Get_fd();
        int newfd = _sock_ptr->Accept();
        AddToArray(newfd , POLLIN);
    }

    void Normalfd_Ready(int fd  , int pos)
    {
        char buffer[1024];
        int n = read(fd  , buffer , sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::string ret = "server get a message : ";;
            ret += buffer;
            write(fd  , ret.c_str() , ret.size());
        }
        else if(n == 0)
        {
            // 对方断开连接了
            
            // 1. 将文件描述符从等待的队列中移除
            // 2. 关闭文件

            _fds_array[pos].fd = -1;

            close(fd);
        }
        else
        {
            // 出错了, 打印日志信息
            Log(Warning) << "read  fail";
        }
    }


    void Dispatcher()
    {
        int listensock = _sock_ptr->Get_fd();
        for(int i = 0 ; i < fds_array_num ; i++)
        {
            int fd = _fds_array[i].fd;
            short eventds = _fds_array[i].revents;
            if(fd == defaultfd || !(eventds & POLLIN)) continue;
            
            if(fd == listensock) 
            {
                Sockfd_Ready();
            }
            else
            {
                Normalfd_Ready(fd , i);
            }
        }
    }

    void Run()
    {
        while(1)
        {
            int n = poll(_fds_array , fds_array_num , -1);
            if(n > 0)
            {
                Dispatcher();
            }
            else if(n == 0)
            {
                Log(Info) << " no file is ready";
            }
            else
            {
                Log(Error) << "poll fail";
            }
        }
    }

private:
    std::shared_ptr<Sock> _sock_ptr;               // 套接字结构体
    struct pollfd _fds_array[fds_array_num];       // 存储所有文件描述符相关信息
};